package wscmd

import (
	"encoding/base64"
	"encoding/json"
	"go.uber.org/zap"
	"google.golang.org/protobuf/proto"
	"strconv"
	"wzgames/internal/admin/adcomm"
	"wzgames/internal/codec/sfs"
	"wzgames/internal/constant"
	"wzgames/internal/gloader"
	"wzgames/internal/model"
	"wzgames/internal/model/agentp"
	"wzgames/internal/model/gamep"
	"wzgames/internal/response"
	"wzgames/pkg/logger"
	"wzgames/pkg/utils/byteutil"
)

func registerSysCmds() {
	cmdSv.RegisterCmd(adcomm.CmdAgentUpdate, agentModify)
	cmdSv.RegisterCmd(adcomm.CmdSysNodeUpdate, sysNodeUpdate)
	cmdSv.RegisterCmd(adcomm.CmdSysConfigUpdate, sysConfigUpdate)
	cmdSv.RegisterCmd(adcomm.CmdGameInstUpdate, sysGameInstUpdate)
}

func agentModify(admin adcomm.IAdmin, ipt interface{}) {
	m := ipt.(*sfs.TSfsObject)
	data := m.GetContent()
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdAgentUpdate, "bad params")
		return
	}
	data = data.GetSFSObject(sfs.ParamId)
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdAgentUpdate, "bad params")
		return
	}
	b, err := base64.StdEncoding.DecodeString(data.GetUtfString("data"))
	if err != nil {
		logger.Error("[WsCmd] sys agent update fail on base64.StdEncoding.DecodeString", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdAgentUpdate, "bad params")
		return
	}
	agent := &agentp.Agent{}
	err = proto.Unmarshal(b, agent)
	if err != nil {
		logger.Error("[WsCmd] sys agent update fail on proto.Unmarshal", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdAgentUpdate, "bad params - 1")
		return
	}

	_, err = gloader.CClient().Store(constant.CcBaseRoot+"/agents/agent-"+strconv.FormatInt(agent.AgtID, 10), byteutil.SliceByteToString(b))
	if err != nil {
		logger.Error("[WsCmd] sys agent update fail on store", zap.Int64("AgentId", agent.AgtID), zap.Error(err))
		admin.ErrMsg(response.ErrInternal, adcomm.CmdAgentUpdate, "")
		return
	}

	msg := response.AcquireMsgO13()
	xw := sfs.XWriter{}
	defer xw.Reset()
	xw.WriteUShort(uint16(2))
	xw.WriteStringS(sfs.CmdKey, adcomm.CmdAgentUpdate)
	xw.WriteSfsObjectPre(sfs.ParamId, uint16(3))
	xw.WriteShortS(sfs.KeyCode, 0)
	xw.WriteLongS("agentId", agent.AgtID)
	xw.WriteStringS("name", agent.AgtName)

	xw.WriteTo(msg)
	admin.SendMessage(msg)
}

func sysNodeUpdate(admin adcomm.IAdmin, ipt interface{}) {
	m := ipt.(*sfs.TSfsObject)
	data := m.GetContent()
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysNodeUpdate, "bad params")
		return
	}
	data = data.GetSFSObject(sfs.ParamId)
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysNodeUpdate, "bad params")
		return
	}
	b, err := base64.StdEncoding.DecodeString(data.GetUtfString("data"))
	if err != nil {
		logger.Error("[WsCmd] sys node update fail on base64.StdEncoding.DecodeString", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysNodeUpdate, "bad params")
		return
	}
	nd := &model.Node{}
	err = json.Unmarshal(b, nd)
	if err != nil {
		logger.Error("[WsCmd] sys node update fail on json.Unmarshal", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysNodeUpdate, "bad params - 1")
		return
	}

	_, err = gloader.CClient().Store(constant.CcNodesRoot+"/"+nd.NodeKey, byteutil.SliceByteToString(b))
	if err != nil {
		logger.Error("[WsCmd] sys node update fail on store", zap.Int64("NodeId", nd.NodeId), zap.Error(err))
		admin.ErrMsg(response.ErrInternal, adcomm.CmdSysNodeUpdate, "")
		return
	}

	msg := response.AcquireMsgO13()
	xw := sfs.XWriter{}
	defer xw.Reset()
	xw.WriteUShort(uint16(2))
	xw.WriteStringS(sfs.CmdKey, adcomm.CmdSysNodeUpdate)
	xw.WriteSfsObjectPre(sfs.ParamId, uint16(5))
	xw.WriteShortS(sfs.KeyCode, 0)
	xw.WriteLongS("nodeId", nd.NodeId)
	xw.WriteStringS("env", string(nd.Env))
	xw.WriteStringS("name", nd.Name)
	xw.WriteStringS("key", nd.NodeKey)

	xw.WriteTo(msg)
	admin.SendMessage(msg)
}

func sysConfigUpdate(admin adcomm.IAdmin, ipt interface{}) {
	m := ipt.(*sfs.TSfsObject)
	data := m.GetContent()
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysConfigUpdate, "bad params")
		return
	}
	data = data.GetSFSObject(sfs.ParamId)
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysConfigUpdate, "bad params")
		return
	}
	b, err := base64.StdEncoding.DecodeString(data.GetUtfString("data"))
	if err != nil {
		logger.Error("[WsCmd] sys config update fail on base64.StdEncoding.DecodeString", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysConfigUpdate, "bad params")
		return
	}
	cfg := &model.GSys{}
	err = json.Unmarshal(b, cfg)
	if err != nil {
		logger.Error("[WsCmd] sys config update fail on proto.Unmarshal", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdSysConfigUpdate, "bad params - 1")
		return
	}

	_, err = gloader.CClient().Store(constant.CcCommRoot+"/sys", byteutil.SliceByteToString(b))
	if err != nil {
		logger.Error("[WsCmd] sys config update fail on store", zap.Error(err))
		admin.ErrMsg(response.ErrInternal, adcomm.CmdSysConfigUpdate, "")
		return
	}

	msg := response.AcquireMsgO13()
	xw := sfs.XWriter{}
	defer xw.Reset()
	xw.WriteUShort(uint16(2))
	xw.WriteStringS(sfs.CmdKey, adcomm.CmdSysConfigUpdate)
	xw.WriteSfsObjectPre(sfs.ParamId, uint16(1))
	xw.WriteShortS(sfs.KeyCode, 0)

	xw.WriteTo(msg)
	admin.SendMessage(msg)
}

func sysGameInstUpdate(admin adcomm.IAdmin, ipt interface{}) {
	m := ipt.(*sfs.TSfsObject)
	data := m.GetContent()
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdGameInstUpdate, "bad params")
		return
	}
	data = data.GetSFSObject(sfs.ParamId)
	if data == nil {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdGameInstUpdate, "bad params")
		return
	}
	b, err := base64.StdEncoding.DecodeString(data.GetUtfString("data"))
	if err != nil {
		logger.Error("[WsCmd] sys game inst update fail on base64.StdEncoding.DecodeString", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdGameInstUpdate, "bad params")
		return
	}
	gameInst := &gamep.GameInst{}
	err = proto.Unmarshal(b, gameInst)
	if err != nil {
		logger.Error("[WsCmd] sys game inst update fail on proto.Unmarshal", zap.Error(err))
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdGameInstUpdate, "bad params - 1")
		return
	}
	var key string
	switch gameInst.Grp {
	case 1:
		key = constant.CcInstanceAviator
	case 2:
		key = constant.CcInstanceG8
	case 3:
		key = constant.CcInstanceRoulette
	}
	if key == "" {
		admin.ErrMsg(response.ErrBadRequest, adcomm.CmdGameInstUpdate, "bad params - 2")
		return
	}
	_, err = gloader.CClient().Store(key+"/"+gameInst.GameTag+"_"+strconv.FormatInt(gameInst.InstID, 10), byteutil.SliceByteToString(b))
	if err != nil {
		logger.Error("[WsCmd] sys game inst update fail on store", zap.Int64("GameInst", gameInst.InstID), zap.Error(err))
		admin.ErrMsg(response.ErrInternal, adcomm.CmdGameInstUpdate, "")
		return
	}

	msg := response.AcquireMsgO13()
	xw := sfs.XWriter{}
	defer xw.Reset()
	xw.WriteUShort(uint16(2))
	xw.WriteStringS(sfs.CmdKey, adcomm.CmdGameInstUpdate)
	xw.WriteSfsObjectPre(sfs.ParamId, uint16(3))
	xw.WriteShortS(sfs.KeyCode, 0)
	xw.WriteLongS("instId", gameInst.InstID)
	xw.WriteStringS("name", gameInst.InstName)

	xw.WriteTo(msg)
	admin.SendMessage(msg)
}
